home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / outp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-24  |  7.5 KB  |  420 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2. static char rcsid[] = "$Header: outp.c,v 2.4 85/08/22 16:05:48 timo Exp $";
  3.  
  4. /*
  5.  * B editor -- Screen management package, lower level output part.
  6.  */
  7.  
  8. #include <ctype.h>
  9.  
  10. #include "b.h"
  11. #include "bobj.h"
  12. #include "node.h"
  13. #include "supr.h"
  14. #include "gram.h"
  15. #include "cell.h"
  16.  
  17.  
  18. #define SOBIT 0200
  19. #define CHAR 0177
  20.  
  21.  
  22. /*
  23.  * Variables used for communication with outfocus.
  24.  */
  25.  
  26. Hidden node thefocus;
  27. Hidden environ wherebuf;
  28. Hidden environ *where = &wherebuf;
  29. Hidden bool realvhole;
  30. Hidden int multiline; /* Height of focus */
  31. Hidden int yfocus;
  32.  
  33. Visible int focy; /* Where the cursor must go */
  34. Visible int focx;
  35.  
  36.  
  37. /*
  38.  * Save position of the focus for use by outnode/outfocus.
  39.  */
  40.  
  41. Visible Procedure
  42. savefocus(ep)
  43.     register environ *ep;
  44. {
  45.     register int sym;
  46.     register int w;
  47.  
  48.     realvhole = No;
  49.     thefocus = Nnil;
  50.     multiline = 0;
  51.     yfocus = Ycoord(ep->focus);
  52.     w = focoffset(ep);
  53.     if (w < 0)
  54.         yfocus += -w;
  55.     w = focwidth(ep);
  56.     if (w < 0) {
  57.         multiline = -w;
  58.         if (focchar(ep) == '\n')
  59.             ++yfocus;
  60.         else
  61.             ++multiline;
  62.         return;
  63.     }
  64.     if (ep->mode == WHOLE) {
  65.         sym = symbol(tree(ep->focus));
  66.         if (sym == Optional)
  67.             ep->mode = ATBEGIN;
  68.     }
  69.     switch(ep->mode) {
  70.     case VHOLE:
  71.         if (ep->s1&1)
  72.             ep->mode = FHOLE;
  73.     case ATBEGIN:
  74.     case ATEND:
  75.     case FHOLE:
  76.         ritevhole(ep);
  77.         switch (ep->mode) {
  78.         case ATBEGIN:
  79.         case FHOLE:
  80.             sym = symbol(tree(ep->focus));
  81.             if (sym == Hole && (ep->mode == ATBEGIN || ep->s2 == 0)) {
  82.                 ep->mode = WHOLE;
  83.                 break;
  84.             }
  85.             /* Fall through */
  86.         case VHOLE:
  87.         case ATEND:
  88.             leftvhole(ep);
  89.             realvhole = 1 + ep->spflag;
  90.         }
  91.     }
  92.     touchpath(&ep->focus); /* Make sure it is a unique pointer */
  93.     thefocus = tree(ep->focus); /* No copy; used for comparison only! */
  94.     where->mode = ep->mode;
  95.     where->s1 = ep->s1;
  96.     where->s2 = ep->s2;
  97.     where->s3 = ep->s3;
  98.     where->spflag = ep->spflag;
  99. }
  100.  
  101.  
  102. /*
  103.  * Incorporate the information saved about the focus.
  104.  */
  105.  
  106. Visible Procedure
  107. setfocus(tops)
  108.     register cell *tops;
  109. {
  110.     register cell *p;
  111.     register int i;
  112.  
  113.     for (p = tops, i = 0; i < yfocus; ++i, p = p->c_link) {
  114.         if (!p) {
  115. #ifndef NDEBUG
  116.             debug("[Focus lost (setfocus)]");
  117. #endif NDEBUG
  118.             return;
  119.         }
  120.     }
  121.     p->c_newvhole = realvhole;
  122.     i = multiline;
  123.     do {
  124.         p->c_newfocus = Yes;
  125.         p = p->c_link;
  126.     } while (--i > 0);
  127. }
  128.  
  129.  
  130. /*
  131.  * Signal that actual updata is started.
  132.  */
  133.  
  134. Visible Procedure
  135. startactupdate(nofocus)
  136.     bool nofocus;
  137. {
  138.     if (nofocus) {
  139.         multiline = 0;
  140.         thefocus = Nnil;
  141.     }
  142. }
  143.  
  144.  
  145. /*
  146.  * Signal the end of the actual update.
  147.  */
  148.  
  149. Visible Procedure
  150. endactupdate()
  151. {
  152. }
  153.  
  154.  
  155. /*
  156.  * Output a line of text.
  157.  */
  158.  
  159. Visible Procedure
  160. outline(p, lineno)
  161.     register cell *p;
  162.     register int lineno;
  163. {
  164.     register node n = p->c_data;
  165.     register int w = width(n);
  166.     register string buf =
  167.         malloc((unsigned) (p->c_newindent + 4 + (w < 0 ? linelen(n) : w)));
  168.             /* some 4 extra for spflag and vhole */
  169.     auto string bp = buf;
  170.     register int i;
  171.     register int endarea = lineno+Space(p)-1;
  172.  
  173.     if (endarea >= winheight)
  174.         endarea = winheight-1;
  175.     for (i = p->c_newindent; i-- > 0; )
  176.         *bp++ = ' ';
  177.     if (!p->c_newfocus) {
  178.         smash(&bp, n, 0);
  179.         *bp = 0;
  180.     }
  181.     else {
  182.         if (multiline)
  183.             smash(&bp, n, SOBIT);
  184.         else if (n == thefocus)
  185.             focsmash(&bp, n);
  186.         else
  187.             smash(&bp, n, 0);
  188.         *bp = 0;
  189.         for (bp = buf; *bp && !(*bp&SOBIT); ++bp)
  190.             ;
  191.         if (*bp&SOBIT) {
  192.             if (focy == Nowhere) {
  193.                 focx = indent + bp-buf;
  194.                 focy = lineno + focx/llength;
  195.                 focx %= llength;
  196.             }
  197.             if (multiline <= 1 && !(bp[1]&SOBIT))
  198.                 *bp &= ~SOBIT; /* Clear mask if just one char in focus */
  199.         }
  200.     }
  201.     trmputdata(lineno, endarea, indent, buf);
  202. }
  203.  
  204.  
  205. /*
  206.  * Smash -- produce a linear version of a node in a buffer (which had
  207.  * better be long enough!).  The buffer pointer is moved to the end of
  208.  * the resulting string.
  209.  * Care is taken to represent the focus.
  210.  * Characters in the focus have their upper bit set.
  211.  */
  212.  
  213. #define Outvhole() \
  214.     (where->spflag && strsmash(pbuf, " ", 0), strsmash(pbuf, "?", SOBIT))
  215.  
  216. Hidden Procedure
  217. focsmash(pbuf, n)
  218.     string *pbuf;
  219.     node n;
  220. {
  221.     value v;
  222.     string str;
  223.     register string *rp;
  224.     register int maxs2;
  225.     register int i;
  226.     register bool ok;
  227.     register int j;
  228.     register int mask;
  229.  
  230.     switch (where->mode) {
  231.  
  232.     case WHOLE:
  233.         smash(pbuf, n, SOBIT);
  234.         break;
  235.  
  236.     case ATBEGIN:
  237.         Outvhole();
  238.         smash(pbuf, n, 0);
  239.         break;
  240.  
  241.     case ATEND:
  242.         smash(pbuf, n, 0);
  243.         Outvhole();
  244.         break;
  245.  
  246.     case VHOLE:
  247.         if (!(where->s1&1)) {
  248.             v = (value) child(n, where->s1/2);
  249.             Assert(Type(v) == Tex);
  250.             subsmash(pbuf, Str(v), where->s2, 0);
  251.             Outvhole();
  252.             strsmash(pbuf, Str(v) + where->s2, 0);
  253.             break;
  254.         }
  255.         /* Else, fall through */
  256.     case FHOLE:
  257.         rp = noderepr(n);
  258.         maxs2 = 2*nchildren(n) + 1;
  259.         for (ok = Yes, i = 1; ok && i <= maxs2; ++i) {
  260.             if (i&1) {
  261.                 if (i == where->s1) {
  262.                     subsmash(pbuf, rp[i/2], where->s2, 0);
  263.                     Outvhole();
  264.                     if (rp[i/2])
  265.                         strsmash(pbuf, rp[i/2] + where->s2, 0);
  266.                 }
  267.                 else
  268.                     strsmash(pbuf, rp[i/2], 0);
  269.             }
  270.             else
  271.                 ok = chismash(pbuf, n, i/2, 0);
  272.         }
  273.         break;
  274.  
  275.     case SUBRANGE:
  276.         rp = noderepr(n);
  277.         maxs2 = 2*nchildren(n) + 1;
  278.         for (ok = Yes, i = 1; ok && i <= maxs2; ++i) {
  279.             if (i&1) {
  280.                 if (i == where->s1) {
  281.                     subsmash(pbuf, rp[i/2], where->s2,0);
  282.                     if (rp[i/2])
  283.                         subsmash(pbuf, rp[i/2] + where->s2,
  284.                             where->s3 - where->s2 + 1, SOBIT);
  285.                     if (rp[i/2])
  286.                         strsmash(pbuf, rp[i/2] + where->s3 + 1, 0);
  287.                 }
  288.                 else
  289.                     strsmash(pbuf, rp[i/2], 0);
  290.             }
  291.             else if (i == where->s1) {
  292.                 v = (value)child(n, i/2);
  293.                 Assert(Type(v) == Tex);
  294.                 str = Str(v);
  295.                 subsmash(pbuf, str, where->s2, 0);
  296.                 subsmash(pbuf, str + where->s2, where->s3 - where->s2 + 1,
  297.                     SOBIT);
  298.                 strsmash(pbuf, str + where->s3 + 1, 0);
  299.             }
  300.             else
  301.                 ok = chismash(pbuf, n, i/2, 0);
  302.         }
  303.         break;
  304.  
  305.     case SUBLIST:
  306.         for (ok = Yes, j = where->s3; j > 0; --j) {
  307.             rp = noderepr(n);
  308.             maxs2 = 2*nchildren(n) - 1;
  309.             for (i = 1; ok && i <= maxs2; ++i) {
  310.                 if (i&1)
  311.                     strsmash(pbuf, rp[i/2], SOBIT);
  312.                 else
  313.                     ok = chismash(pbuf, n, i/2, SOBIT);
  314.             }
  315.             if (ok)
  316.                 n = lastchild(n);
  317.         }
  318.         if (ok)
  319.             smash(pbuf, n, 0);
  320.         break;
  321.  
  322.     case SUBSET:
  323.         rp = noderepr(n);
  324.         maxs2 = 2*nchildren(n) + 1;
  325.         mask = 0;
  326.         for (ok = Yes, i = 1; ok && i <= maxs2; ++i) {
  327.             if (i == where->s1)
  328.                 mask = SOBIT;
  329.             if (i&1)
  330.                 strsmash(pbuf, rp[i/2], mask);
  331.             else
  332.                 ok = chismash(pbuf, n, i/2, mask);
  333.             if (i == where->s2)
  334.                 mask = 0;
  335.         }
  336.         break;
  337.  
  338.     default:
  339.         Abort();
  340.     }
  341. }
  342.  
  343. Hidden Procedure
  344. smash(pbuf, n, mask)
  345.     register string *pbuf;
  346.     register node n;
  347.     register int mask;
  348. {
  349.     register string *rp;
  350.     register int i;
  351.     register int nch;
  352.  
  353.     rp = noderepr(n);
  354.     strsmash(pbuf, rp[0], mask);
  355.     nch = nchildren(n);
  356.     for (i = 1; i <= nch; ++i) {
  357.         if (!chismash(pbuf, n, i, mask))
  358.             break;
  359.         strsmash(pbuf, rp[i], mask);
  360.     }
  361. }
  362.  
  363. Hidden Procedure
  364. strsmash(pbuf, str, mask)
  365.     register string *pbuf;
  366.     register string str;
  367.     register int mask;
  368. {
  369.     if (!str)
  370.         return;
  371.     for (; *str; ++str) {
  372.         if (isprint(*str) || *str == ' ')
  373.             **pbuf = *str|mask, ++*pbuf;
  374.     }
  375. }
  376.  
  377. Hidden Procedure
  378. subsmash(pbuf, str, len, mask)
  379.     register string *pbuf;
  380.     register string str;
  381.     register int len;
  382.     register int mask;
  383. {
  384.     if (!str)
  385.         return;
  386.     for (; len > 0 && *str; --len, ++str) {
  387.         if (isprint(*str) || *str == ' ')
  388.             **pbuf = *str|mask, ++*pbuf;
  389.     }
  390. }
  391.  
  392.  
  393. /*
  394.  * Smash a node's child.
  395.  * Return No if it contained a newline (to stop the parent).
  396.  */
  397.  
  398. Hidden bool
  399. chismash(pbuf, n, i, mask)
  400.     register string *pbuf;
  401.     register node n;
  402.     register int i;
  403. {
  404.     register node nn = child(n, i);
  405.     register int w;
  406.  
  407.     if (Type(nn) == Tex) {
  408.         strsmash(pbuf, Str((value)nn), mask);
  409.         return Yes;
  410.     }
  411.     w = width(nn);
  412.     if (w < 0 && Fw_negative(noderepr(nn)[0]))
  413.         return No;
  414.     if (nn == thefocus)
  415.         focsmash(pbuf, nn);
  416.     else
  417.         smash(pbuf, nn, mask);
  418.     return w >= 0;
  419. }
  420.